home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / CBA / MOONTOOL / !MoonTool / !Help next >
Text File  |  1993-08-09  |  35KB  |  1,123 lines

  1. /*
  2.                         Moon Tool for the Archimedes
  3.                         ============================
  4.  
  5.            Sun Workstation version ................ John Walker
  6.            Archimedes Risc OS 3.1 port ............ Edouard Poor
  7.  
  8.                    This  program is in the public domain: 
  9.              "Do what thou wilt shall be the whole of the law".
  10.  
  11.  
  12. Introduction
  13. ============
  14.  
  15.    MoonTool is a program designed give you the following infomation:
  16.  
  17.       o  Phase of the Moon
  18.  
  19.       o  Age of the Moon
  20.  
  21.       o  Distance to the moon
  22.  
  23.       o  Dates of the Last and Next New moon as well as the First and
  24.          Last Quarters and the Full Moon.
  25.  
  26.       o  Angle the Moon subtends
  27.  
  28.    In addition it also gives you information about:
  29.  
  30.       o  Time and Date in Julian, Local and Universal (GMT) times.
  31.  
  32.       o  Distance to the Sun
  33.  
  34.       o  Angle the Sun subtends
  35.  
  36.    An invaluable tool for those of you who don't like going outside to look
  37.    at the moon, all the nethack players among you, astronomers who like
  38.    to know when the moon it new and thus the stars are at their best viewing,
  39.    or indeed anyone who just really needs to exactly how far away the moon
  40.    and sun are...
  41.  
  42.  
  43. Interface
  44. =========
  45.  
  46.    The program starts up in it's iconised mode, giving you a simple window
  47.    with a single button displaying a picture of the moon as it appears
  48.    in the sky. You can move the window with its title bar, or click on the
  49.    icon to bring up the full, un-iconised, view.
  50.  
  51.    In un-iconised mode you are presented with all the information about the
  52.    current time, the moons distance and age, the suns distance, and the
  53.    "Moon Phase" icon. Looking to the top right of the window you will see
  54.    that it has a full-size icon; clicking on this will reveal additional
  55.    information about the dates of the phases of the moon (all in UTC, or
  56.    Universal Time).
  57.  
  58.    Clicking again on the "Moon Phase" icon of the moons current appearance
  59.    will put the program back into iconised mode.
  60.  
  61.    Quitting the prgram simply consists of closing the window when it is
  62.    in un-iconised mode.
  63.  
  64.  
  65. Risc OS 3.1 Notes
  66. =================
  67.  
  68.    This program needs both Local Time and Greenwich Mean Time set up
  69.    correctly in your machine. 
  70.  
  71.    This requires two things-- Firstly setting the configured time in your
  72.    machine to Greenwich Mean Time then getting the time correct for
  73.    where you live by setting the Congfiguration Setting 'TimeZone' (you
  74.    can type "help TimeZone" on the command line). This step will probably
  75.    be unnessesary in the UK where you are on GMT anyway...
  76.    Where I live (in New Zealand) I use "configure TimeZone +12:0"
  77.  
  78.    The second step is to do with daylight savings-- Use !Alarm to toggle
  79.    between daylight savings on and off instead of altering the time or
  80.    the TimeZone offset. (Daylight Savings Time or DST is labeled 'BST'
  81.    in !Alarms 'Set Time' window, which stands for British Summer Time,
  82.    because Acorn is Very Good at Internationalisation...)
  83.  
  84.    If you set and maintain the time in the method outlined above, you
  85.    will always be able to have the correct time, and be able to work
  86.    out the time in GMT or UTC as well, as will any program that needs
  87.    to know the time in both local and universal. C programs that use
  88.    localtime() and gmtime(), for example, need this.
  89.    
  90.  
  91. Problems
  92. ========
  93.  
  94.    There are no problems or bugs with this program. It is perfect in every
  95.    way and any difficulties you may experience are one of the three following
  96.    people, or organisation's fault:
  97.  
  98.       o  Yourself
  99.  
  100.       o  Your Acorn Dealer
  101.  
  102.       o  Acorn Computers Limited
  103.  
  104.    For example you might say "When I run !MoonTool on my RO2 machine it
  105.    crashes" - This would be your fault for not purchasing Risc OS 3.1 yet.
  106.  
  107.    You might say "In 256 colour mode the button plinths in, but it also
  108.    inverts as well" - This would be Acorns fault for not having better
  109.    'Kwality Kontrol' on its operating systems.
  110.  
  111.    Also someone might complain "When the moon behind a cloud I can't see it
  112.    but I can still it on my computer. Could you set it up so that it's
  113.    visiability is always the same as the real moon?" - This would be their
  114.    dealers fault for selling a computer to someone whose IQ was obviously
  115.    in the low 70's...
  116.  
  117.    In short, if you havn't worked it out yet, I take no responibility for
  118.    anything at all to do with this program.
  119.  
  120.  
  121. To Be Done
  122. ==========
  123.  
  124.    Well everything is actually about as well done as it's likely to get,
  125.    but if anyone wants to send me any improvments to the address below
  126.    I'd be very grateful, and will release anothr version with your
  127.    modifications and credit.
  128.  
  129.    Also if anyone can design me a better Filer Icon I'd be most happy
  130.    to replace the one I've got at the moment...
  131.  
  132.    If anyone feels like spell checking this !Help file I'm sure hundreds,
  133.    if not thousands, of english speakers around the world would be grateful
  134.    to you :-)
  135.  
  136.  
  137. Author Info (Archimedes Version)
  138. ================================
  139.  
  140.    Send all snail mail/money orders/cheques/cash to:
  141.          Edouard Poor
  142.          15 Stanley Pt Rd
  143.          Devonport
  144.          Auckland
  145.          New Zealand
  146.  
  147.    Email/uu-files may be addressed to:
  148.          epoo1@cs.aukuni.ac.nz    (valid until at least March 1994)
  149.          edouard@nacjack.gen.nz   (not used very often)
  150.  
  151.    Voice line:
  152.          +64 9 4450330
  153.  
  154.  
  155. Bibliography
  156. ============
  157.  
  158.    The algorithms used in this program to calculate the positions Sun and
  159.    Moon as seen from the Earth are given in the book "Practical Astronomy
  160.    With Your Calculator" by Peter Duffett-Smith, Second Edition, Cambridge
  161.    University Press, 1981. Ignore the word "Calculator" in the title; this
  162.    is an essential reference if you're interested in developing software
  163.    which calculates planetary positions, orbits, eclipses, and the like. If
  164.    you're interested in pursuing such programming, you should also obtain:
  165.  
  166.    "Astronomical Formulae for Calculators" by Jean Meeus, Third Edition,
  167.    Willmann-Bell, 1985. A must-have.
  168.  
  169.    "Planetary Programs and Tables from -4000 to +2800" by Pierre Bretagnon
  170.    and Jean-Louis Simon, Willmann-Bell, 1986. If you want the utmost
  171.    (outside of JPL) accuracy for the planets, it's here.
  172.  
  173.    "Celestial BASIC" by Eric Burgess, Revised Edition, Sybex, 1985. Very
  174.    cookbook oriented, and many of the algorithms are hard to dig out of the
  175.    turgid BASIC code, but you'll probably want it anyway.
  176.  
  177.    Many of these references can be obtained from Willmann-Bell, P.O. Box
  178.    35025, Richmond, VA 23235, USA. Phone: (804) 320-7016. In addition to
  179.    their own publications, they stock most of the standard references for
  180.    mathematical and positional astronomy.
  181.  
  182.  
  183. Sun Workstation (Original) Author Info
  184. ======================================
  185.  
  186.    A Moon for the Sun
  187.  
  188.    Release 2.0
  189.  
  190.    Designed and implemented by John Walker in December 1987,
  191.    revised and updated in February of 1988.
  192.  
  193.    This program was written by:
  194.  
  195.        John Walker
  196.        Autodesk, Inc.
  197.        2320 Marinship Way
  198.        Sausalito, CA  94965
  199.        (415) 332-2344 Ext. 829
  200.  
  201.        Usenet: {sun!well}!acad!kelvin
  202.  
  203.    I'd appreciate receiving any bug fixes and/or enhancements, which I'll
  204.    incorporate in future versions of the program. Please leave the original
  205.    attribution information intact so that credit and blame may be properly
  206.    apportioned.
  207.  
  208.  
  209. Source Code
  210. =========== 
  211.  
  212.    Well it was originally compiled with my own personal library "QDD_Lib"
  213.    but it uses very few calls, and they are all, unlike Acorns "RISC_OSLib"
  214.    ones, very easy to read. It should be very easy for anyone with a C
  215.    compiler and any set of wimp libraries to convert this program to
  216.    compile under their own set-up.
  217.  
  218.    Enjoy.
  219.  
  220.  *
  221.  *
  222.  *
  223.  *  Astronomical constants 
  224.  */
  225. #define epoch       2444238.5      /* 1980 January 0.0 */
  226.  
  227. /*
  228.  *  Constants defining the Sun's apparent orbit  
  229.  */
  230. #define elonge      278.833540     /* Ecliptic longitude of the Sun at epoch 1980.0 */
  231. #define elongp      282.596403     /* Ecliptic longitude of the Sun at perigee */
  232. #define eccent      0.016718       /* Eccentricity of Earth's orbit */
  233. #define sunsmax     1.495985e8     /* Semi-major axis of Earth's orbit, km */
  234. #define sunangsiz   0.533128       /* Sun's angular size, degs, at semi-major axis distance */
  235.  
  236. /*
  237.  *  Elements of the Moon's orbit, epoch 1980.0
  238.  */
  239. #define mmlong      64.975464      /* Moon's mean lonigitude at the epoch */
  240. #define mmlongp     349.383063     /* Mean longitude of the perigee at the epoch */
  241. #define mlnode      151.950429     /* Mean longitude of the node at the epoch */
  242. #define minc        5.145396       /* Inclination of the Moon's orbit */
  243. #define mecc        0.054900       /* Eccentricity of the Moon's orbit */
  244. #define mangsiz     0.5181         /* Moon's angular size at distance a from Earth */
  245. #define msmax       384401.0       /* Semi-major axis of Moon's orbit in km */
  246. #define mparallax   0.9507         /* Parallax at distance a from Earth */
  247. #define synmonth    29.53058868    /* Synodic month (new Moon to new Moon) */
  248. #define lunatbase   2423436.0      /* Base date for E. W. Brown's numbered series
  249.                                       of lunations (1923 January 16) */
  250. /*
  251.  *  Properties of the Earth
  252.  */
  253. #define earthrad    6378.16        /* Radius of Earth in kilometres */
  254.  
  255. #include <stdio.h>
  256. #include <stdlib.h>
  257. #include <math.h>
  258. #include <time.h>
  259. #include <string.h>
  260. #include <stdarg.h>
  261.  
  262. /*
  263.  *  Handy mathematical functions and constants
  264.  */
  265. #define EPSILON 1E-6  
  266. #define PI 3.14159265358979323846  /* Assume not near black hole nor in Tennessee */
  267. #define sgn(x) (((x) < 0) ? -1 : ((x) > 0 ? 1 : 0))       /* Extract sign */
  268. #define abs(x) ((x) < 0 ? (-(x)) : (x))                   /* Absolute val */
  269. #define fixangle(a) ((a) - 360.0 * (floor((a) / 360.0)))  /* Fix angle    */
  270. #define torad(d) ((d) * (PI / 180.0))                     /* Deg->Rad     */
  271. #define todeg(d) ((d) * (180.0 / PI))                     /* Rad->Deg     */
  272. #define dsin(x) (sin(torad((x))))                         /* Sin from deg */
  273. #define dcos(x) (cos(torad((x))))                         /* Cos from deg */
  274.  
  275. #define FALSE 0
  276. #define TRUE  1
  277.  
  278. static int testmode = FALSE;       /* Rapid warp through time for debugging */
  279. static int Iconised = TRUE;
  280.  
  281. /*  Forward functions  */
  282.  
  283. double jtime(struct tm *);
  284. double phase(double, double *, double *, double *, double *, double *, double *);
  285. void   phasehunt(double, double *);
  286. void   ringgg(void);
  287. void   drawmoon(double);
  288. void   jyear(double, int *, int *, int *);
  289. void   jhms(double, int *, int *, int *);
  290.  
  291. #define Plural(x) (x) == 1 ? "" : "s"
  292.  
  293.  
  294. /***********************************************/
  295.  
  296. #include "Wimp.h"
  297. #include "GFX.h"
  298.  
  299. #define Julian_Date               4
  300. #define Local_Time                7
  301. #define Local_Date                8
  302. #define Universal_Time            11
  303. #define Universal_Date            12
  304. #define Moon_Subtends             17
  305. #define MoonDistance_Kilometers   20
  306. #define MoonDistance_Radii        21
  307. #define MoonAge_Days              27
  308. #define MoonAge_Hours             28
  309. #define MoonAge_Minutes           29
  310. #define Sun_Subtends              34
  311. #define SunDistance_Kilometers    37
  312. #define SunDistance_AU            38
  313. #define Phases_LastNewMoon        45
  314. #define Phases_FirstQuarter       48
  315. #define Phases_FullMoon           51
  316. #define Phases_LastQuarter        54
  317. #define Phases_NextNewMoon        57
  318. #define Phases_CurrentLunation    61
  319.  
  320. taskhandle   OurTaskHandle;
  321. windowhandle MoonTool;
  322. windowhandle MoonIcon;
  323.  
  324. char temp[128];   /* A temporary string buffer */
  325.  
  326. /*
  327.  *  Useful Risc OS functions  
  328.  */ 
  329. void Icon_SmartPrint(iconhandle i, char *format, ...)
  330.     {
  331.     va_list    argp;
  332.     iconstate  info;
  333.     char      *source;
  334.     char      *dest;
  335.     int        length;
  336.  
  337.     va_start(argp, format);
  338.     vsprintf(temp, format, argp);
  339.     va_end(argp);
  340.  
  341.     Wimp_GetIconState(MoonTool, i, &info);
  342.  
  343.     if(info.icon.flags.feild.indirected)
  344.         {
  345.         dest = info.icon.data.indirectedtext.buffer;
  346.         length = info.icon.data.indirectedtext.bufflen-1;
  347.         }
  348.     else
  349.         {
  350.         dest = info.icon.data.text;
  351.         length = 11;
  352.         }
  353.     source = temp;
  354.  
  355.     if(strncmp(dest, source, length) != 0)
  356.         {
  357.         strncpy(dest, source, length);
  358.         Wimp_SetIconState(MoonTool, i, 0, 0);
  359.         }
  360.     }
  361.  
  362.  
  363. void StartWimp(void)
  364.     {
  365.     int           i;
  366.     int           isize;
  367.     int           windowsize;
  368.     BOOL          fontspresent;
  369.     window       *moontoolwindow;
  370.     window       *mooniconwindow;
  371.     window       *scratchwindow;
  372.     void         *moontoolispace;
  373.     void         *mooniconispace;
  374.     windowstate   wstate;
  375.     templatefonts fonts;
  376.  
  377.     /*
  378.     **      Initialise my I/O variables ...
  379.     */
  380.     Wimp_Initialise200("Moon Tool", &OurTaskHandle);
  381.  
  382.     Wimp_OpenTemplate("MoonTool:Templates");
  383.  
  384.     Wimp_NamedTemplateSize("MoonTool", &isize, &windowsize, &fontspresent);
  385.     for(i=0; i<256; i++)
  386.         fonts.font[i] = 0;
  387.     scratchwindow = (window *) malloc(windowsize+isize);
  388.     moontoolispace = (void *)   malloc(isize);
  389.     Wimp_LoadNamedTemplate(scratchwindow, "MoonTool", moontoolispace, isize, &fonts);
  390.     Wimp_CreateWindow(scratchwindow, &MoonTool);
  391.  
  392.     Wimp_NamedTemplateSize("MoonIcon", &isize, &windowsize, &fontspresent);
  393.     scratchwindow = (window *) realloc(scratchwindow, windowsize+isize);
  394.     mooniconispace = (void *)   malloc(isize);
  395.     Wimp_LoadNamedTemplate(scratchwindow, "MoonIcon", mooniconispace, isize, NULL);
  396.     Wimp_CreateWindow(scratchwindow, &MoonIcon);
  397.  
  398.     Wimp_CloseTemplate();
  399.  
  400.     if(Iconised)
  401.         wstate.handle = MoonIcon;
  402.     else
  403.         wstate.handle = MoonTool;
  404.  
  405.     Wimp_GetWindowState(&wstate);
  406.     Wimp_OpenWindow((openwindowinfo *) &wstate);
  407.  
  408.     free(scratchwindow);
  409.     }
  410.  
  411.  
  412. /*
  413.  *  Dispatch Poll
  414.  */
  415. void DispatchPoll(eventinfo *event)
  416.     {
  417.     switch (event->type)
  418.         {
  419.         case Open_Window_Request :
  420.             Wimp_OpenWindow(&event->data.window);
  421.             break;
  422.  
  423.         case Close_Window_Request :
  424.             Wimp_CloseDown();
  425.             exit(0);
  426.             break;
  427.  
  428.         case Mouse_Button_Change:
  429.             {
  430.             windowstate state;
  431.  
  432.             if(event->data.buttonchange.pointerinfo.buttons.feild.menu)
  433.                 /*MakeMenu(event)*/;
  434.             else 
  435.                 {
  436.                 eventinfo dummyevent;
  437.  
  438.                 if(event->data.buttonchange.pointerinfo.window == MoonTool &&
  439.                    event->data.buttonchange.pointerinfo.icon == 42)
  440.                     {
  441.                     Wimp_CloseWindow(MoonTool);
  442.                     
  443.                     Wimp_PollIdleSeconds(&dummyevent, 0, 0);
  444.                     DispatchPoll(&dummyevent);
  445.  
  446.                     state.handle = MoonIcon;
  447.                     Wimp_GetWindowState(&state);
  448.                     state.behind = OPEN_ON_TOP;
  449.                     Wimp_OpenWindow((openwindowinfo *) &state);
  450.  
  451.                     Iconised = TRUE;
  452.                     }
  453.                 if(event->data.buttonchange.pointerinfo.window == MoonIcon)
  454.                     {
  455.                     Wimp_CloseWindow(MoonIcon);
  456.                     
  457.                     Wimp_PollIdleSeconds(&dummyevent, 0, 0);
  458.                     DispatchPoll(&dummyevent);
  459.  
  460.                     Iconised = FALSE;  /* Have to set this before we call ringgg(); */
  461.                     ringgg();
  462.  
  463.                     state.handle = MoonTool;
  464.                     Wimp_GetWindowState(&state);
  465.                     state.behind = OPEN_ON_TOP;
  466.                     Wimp_OpenWindow((openwindowinfo *) &state);
  467.                     }
  468.                 }
  469.             }
  470.             break;
  471.  
  472.         case Menu_Select:
  473.             {
  474.             if(event->data.menu[0] == 1) exit(0);
  475.             }
  476.             break;
  477.  
  478.         case Key_Pressed:
  479.             Wimp_ProcessKey(event->data.key.code);
  480.             break;
  481.  
  482.         case Send_Message:
  483.         case Send_Message_Acknowledged:
  484.             switch(event->data.message.header.type)
  485.                 {
  486.                 case Message_CloseDown:
  487.                     Wimp_CloseDown();
  488.                     exit(1);
  489.                     break;
  490.                 }
  491.             break;
  492.         }
  493.     }
  494.  
  495.  
  496.  
  497. /*  Main program  */
  498.  
  499. int main(int argc, char *argv[])
  500.     {
  501.     int i;
  502.     int delay;
  503.     eventmask mask = 0;
  504.     eventinfo event;
  505.  
  506.     for (i = 1; i < argc; i++)
  507.         {
  508.         if (*argv[i] == '-' && argv[i][1] == 't')
  509.             testmode = TRUE;
  510.         }
  511.  
  512.     StartWimp();
  513.     ringgg();
  514.  
  515.     while(TRUE)
  516.         {
  517.         if(Iconised && !testmode)
  518.             delay = 6000;
  519.         else
  520.             delay = 90;
  521.         Wimp_PollIdleSeconds(&event, mask, delay);
  522.  
  523.         if(event.type == Null_Reason_Code)
  524.             ringgg();
  525.         else
  526.             DispatchPoll(&event);
  527.         }
  528.     }
  529.  
  530.  
  531. /*
  532.  *  DRAWMOON  --  Construct icon for moon, given phase of moon.
  533.  */
  534.  
  535. int IconSpanlist[36][2];
  536. #define Left  0
  537. #define Right 1
  538. #define XMid 35
  539.                                              
  540. void drawmoon(double ph)
  541.     {
  542.     int           i, j, lx, rx;
  543.     double        cp, xscale, d;
  544.     BOOL          IconChanged = FALSE;
  545.     spritecontext SavedContext;
  546.  
  547.     xscale = cos(2 * PI * ph);
  548.  
  549.     for (i = 0; i < 29; i++)
  550.         {
  551.         d = (i*2.0+1.0) / 29.0;
  552.         if(d <= 1.0)
  553.             d = 1.0 - d;
  554.         else
  555.             d = d - 1.0;    
  556.         cp = 31.0 * cos(asin(d));
  557.  
  558.         if (ph < 0.5)
  559.             {
  560.             rx = 1000;
  561.             lx = XMid - xscale * cp;
  562.             }
  563.         else
  564.             {
  565.             lx = 0;
  566.             rx = XMid + xscale * cp;
  567.             }
  568.  
  569.         if((IconSpanlist[i][Left] != lx) || (IconSpanlist[i][Right] != rx))
  570.             {
  571.             IconSpanlist[i][Left] = lx;
  572.             IconSpanlist[i][Right] = rx;
  573.             IconChanged = TRUE;
  574.             }
  575.         }
  576.     /*  
  577.      *  Only update icon if it changed (this eliminates gratuitous
  578.      *  flashing of the icon on-screen).
  579.      */
  580.     if(IconChanged)
  581.         {
  582.         GFX_ChangeContextToSpriteMask(1, "the_moon", &SavedContext);
  583.         GFX_GCOL(15);                  /* No Mask */
  584.         GFX_Rectangle(0,0,1000,1000);  /* Clear whole sprite */
  585.         GFX_GCOL(0);                   /* Mask */
  586.         for(i=0; i<29; i++)
  587.             {
  588.             GFX_Line(IconSpanlist[i][Left]*2, i*4 + 8, IconSpanlist[i][Right]*2, i*4 + 8);
  589.             }
  590.         GFX_RestoreContext(&SavedContext);
  591.  
  592.         Wimp_SetIconState(MoonTool, 41, 0, 0);
  593.         Wimp_SetIconState(MoonIcon, 0, 0, 0);
  594.         }
  595.     }
  596.  
  597. /*  RINGGG  --  Update status on interval timer ticks and redraw
  598.                 window if needed.  */
  599.  
  600. void ringgg(void)
  601.     {
  602.     int lunation, wclosed;
  603.     time_t t;
  604.     double jd, p, aom, cphase, cdist, cangdia, csund, csuang, lptime;
  605.     static double phasar[5];
  606.     static double nptime = 0.0; /* Next new moon time */
  607.     static int updyet = 0;      /* Update interval when window closed */
  608.     static int firstime = TRUE; /* Calculate text page first time */
  609.     char amsg[12], tbuf[80];
  610.     static double faketime = 0.0;
  611.     static short moonilast[64][4] = {0};
  612.     int yy, mm, dd, hh, mmm, ss;
  613.     struct tm *gm;
  614.     static char *moname[] = {"January", "February", "March", "April",
  615.                              "May", "June", "July", "August", "September",
  616.                              "October", "November", "December"};
  617.  
  618.         (void) time(&t);
  619.         jd = jtime((gm = gmtime(&t)));
  620.  
  621.         if(testmode)
  622.             {
  623.             if (faketime == 0.0)
  624.                 faketime = jd + 1;
  625.             else
  626.                 faketime += 1.0 / 24;
  627.             jd = faketime;
  628.             }
  629.  
  630.         p = phase(jd, &cphase, &aom, &cdist, &cangdia, &csund, &csuang);
  631.         /*
  632.          *  Calculate times of phases of this lunation.
  633.          *  This is sufficiently time-consuming that
  634.          *  we only do it once a month.
  635.          */
  636.         if(jd > nptime)
  637.             {
  638.             phasehunt(jd, phasar);  /* X-pensive call */
  639.             }
  640.  
  641.         drawmoon(p);
  642.  
  643.         /* If we're iconic, there's nothing more to do. */
  644.  
  645.         if (Iconised && !firstime)
  646.             return;
  647.  
  648.         /* 
  649.          *  Update textual information for open window
  650.          */
  651.         firstime = FALSE;
  652.  
  653.         Icon_SmartPrint(Julian_Date, "%.5f", jd + 0.5);
  654.  
  655.         if(testmode)
  656.             {
  657.             jyear(jd, &yy, &mm, &dd);
  658.             jhms(jd, &hh, &mmm, &ss);
  659.             Icon_SmartPrint(Universal_Time, "%02d:%02d:%02d", hh, mmm, ss);
  660.             Icon_SmartPrint(Universal_Date, "%d %s %d", dd, moname[mm-1], yy);
  661.             }
  662.         else
  663.             {
  664.             Icon_SmartPrint(Universal_Time, "%02d:%02d:%02d", gm->tm_hour, gm->tm_min, gm->tm_sec);
  665.             Icon_SmartPrint(Universal_Date, "%d %s %d", gm->tm_mday, moname[gm->tm_mon], gm->tm_year + 1900);
  666.             }
  667.  
  668.         gm = localtime(&t);
  669.         if(testmode)
  670.             {
  671.             Icon_SmartPrint(Local_Time, "--:--:--");
  672.             Icon_SmartPrint(Local_Date, "(Test Mode)");
  673.             }
  674.         else
  675.             {
  676.             Icon_SmartPrint(Local_Time, "%02d:%02d:%02d", gm->tm_hour, gm->tm_min, gm->tm_sec);
  677.             Icon_SmartPrint(Local_Date, "%d %s %d", gm->tm_mday, moname[gm->tm_mon], gm->tm_year + 1900);
  678.             }
  679.  
  680.         /*
  681.          *  sprintf(tbuf, "Moon phase:      %d%%   0%% = New, 100%% = Full  ",
  682.          *         (int) (cphase * 100));
  683.          *   prt(5);
  684.          */
  685.  
  686.         /*
  687.          *  Information about the Moon
  688.          */
  689.         Icon_SmartPrint(Moon_Subtends, "%.4f°", cangdia);
  690.  
  691.         Icon_SmartPrint(MoonDistance_Kilometers, "%ld kilometres", (long) cdist);
  692.         Icon_SmartPrint(MoonDistance_Radii, "%.1f Earth radii", cdist / earthrad);
  693.  
  694.         aom = jd - phasar[0]; /* Cos it was wrong -- Edouard Poor */
  695.  
  696.         Icon_SmartPrint(MoonAge_Days, "%d", (int) aom);
  697.         Icon_SmartPrint(MoonAge_Hours, "%d", ((int) (24 * (aom - floor(aom)))));
  698.         Icon_SmartPrint(MoonAge_Minutes, "%d", ((int) (1440 * (aom - floor(aom)))) % 60);
  699.  
  700.         /*  
  701.          *  Edit information about the Sun
  702.          */
  703.         Icon_SmartPrint(Sun_Subtends, "%.4f°", csuang);
  704.  
  705.         Icon_SmartPrint(SunDistance_Kilometers, "%.0f kilometres", csund);
  706.         Icon_SmartPrint(SunDistance_AU, "%.3f A.U.", csund / sunsmax);
  707.  
  708.         /*
  709.          *  Calculate times of phases of this lunation.
  710.          *  This is sufficiently time-consuming that
  711.          *  we only do it once a month.
  712.          */
  713.         if(jd > nptime)
  714.             {
  715.             lptime = phasar[0];
  716.             jyear(lptime, &yy, &mm, &dd);
  717.             jhms(lptime, &hh, &mmm, &ss);
  718.             Icon_SmartPrint(Phases_LastNewMoon, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
  719.  
  720.             lptime = phasar[1];
  721.             jyear(lptime, &yy, &mm, &dd);
  722.             jhms(lptime, &hh, &mmm, &ss);
  723.             Icon_SmartPrint(Phases_FirstQuarter, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
  724.    
  725.             lptime = phasar[2];
  726.             jyear(lptime, &yy, &mm, &dd);
  727.             jhms(lptime, &hh, &mmm, &ss);
  728.             Icon_SmartPrint(Phases_FullMoon, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
  729.    
  730.             lptime = phasar[3];
  731.             jyear(lptime, &yy, &mm, &dd);
  732.             jhms(lptime, &hh, &mmm, &ss);
  733.             Icon_SmartPrint(Phases_LastQuarter, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
  734.    
  735.             nptime = phasar[4];
  736.             jyear(nptime, &yy, &mm, &dd);
  737.             jhms(nptime, &hh, &mmm, &ss);
  738.             Icon_SmartPrint(Phases_NextNewMoon, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
  739.  
  740.             lunation = floor(((lptime + 7) - lunatbase) / synmonth) + 1;
  741.             Icon_SmartPrint(Phases_CurrentLunation, "%d", lunation);
  742.             }
  743.         }
  744.  
  745. /*  JDATE  --  Convert internal GMT date and time to Julian day
  746.                and fraction.  */
  747.  
  748. long jdate(struct tm *t)
  749.     {
  750.     long c, m, y;
  751.  
  752.     y = t->tm_year + 1900;
  753.     m = t->tm_mon + 1;
  754.     if (m > 2)
  755.        m = m - 3;
  756.     else
  757.         {
  758.         m = m + 9;
  759.         y = y - 1;
  760.         }
  761.     c = y / 100L;              /* Compute century */
  762.     y -= 100L * c;
  763.     return t->tm_mday + (c * 146097L) / 4 + (y * 1461L) / 4 +
  764.             (m * 153L + 2) / 5 + 1721119L;
  765.     }
  766.  
  767. /* JTIME --    Convert internal GMT date and time to astronomical Julian
  768.                time (i.e. Julian date plus day fraction, expressed as
  769.                a double).  */
  770.  
  771. double jtime(struct tm *t)
  772.     {
  773.     return (jdate(t) - 0.5) + 
  774.         (t->tm_sec + 60 * (t->tm_min + 60 * t->tm_hour)) / 86400.0;
  775.     }
  776.  
  777. /*  JYEAR  --  Convert Julian date to year, month, day, which are
  778.                returned via integer pointers to integers.  */
  779.  
  780. void jyear(double td, int *yy, int *mm, int *dd)
  781.     {
  782.     double j, d, y, m;
  783.  
  784.     td += 0.5;                 /* Astronomical to civil */
  785.     j = floor(td);
  786.     j = j - 1721119.0;
  787.     y = floor(((4 * j) - 1) / 146097.0);
  788.     j = (j * 4.0) - (1.0 + (146097.0 * y));
  789.     d = floor(j / 4.0);
  790.     j = floor(((4.0 * d) + 3.0) / 1461.0);
  791.     d = ((4.0 * d) + 3.0) - (1461.0 * j);
  792.     d = floor((d + 4.0) / 4.0);
  793.     m = floor(((5.0 * d) - 3) / 153.0);
  794.     d = (5.0 * d) - (3.0 + (153.0 * m));
  795.     d = floor((d + 5.0) / 5.0);
  796.     y = (100.0 * y) + j;
  797.     if (m < 10.0)
  798.         m = m + 3;
  799.     else
  800.         {
  801.         m = m - 9;
  802.         y = y + 1;
  803.         }
  804.     *yy = y;
  805.     *mm = m;
  806.     *dd = d;
  807.     }
  808.  
  809. /*  JHMS  --  Convert Julian time to hour, minutes, and seconds.  */
  810.  
  811. void jhms(double j, int *h, int *m, int *s)
  812.     {
  813.     long ij;
  814.  
  815.     j += 0.5;                  /* Astronomical to civil */
  816.     ij = (j - floor(j)) * 86400.0;
  817.     *h = ij / 3600L;
  818.     *m = (ij / 60L) % 60L;
  819.     *s = ij % 60L;
  820.     }
  821.  
  822. /*  MEANPHASE  --  Calculates mean phase of the Moon for a given
  823.                    base date and desired phase:
  824.                        0.0   New Moon
  825.                        0.25  First quarter
  826.                        0.5   Full moon
  827.                        0.75  Last quarter
  828.                     Beware!!!  This routine returns meaningless
  829.                     results for any other phase arguments.  Don't
  830.                     attempt to generalise it without understanding
  831.                     that the motion of the moon is far more complicated
  832.                     that this calculation reveals. */
  833.  
  834. double meanphase(double sdate, double phase, double *usek)
  835.     {
  836.     int yy, mm, dd;
  837.     double k, t, t2, t3, nt1;
  838.  
  839.     jyear(sdate, &yy, &mm, &dd);
  840.  
  841.     k = (yy + ((mm - 1) * (1.0 / 12.0)) - 1900) * 12.3685;
  842.  
  843.     /* Time in Julian centuries from 1900 January 0.5 */
  844.     t = (sdate - 2415020.0) / 36525;
  845.     t2 = t * t;                /* Square for frequent use */
  846.     t3 = t2 * t;               /* Cube for frequent use */
  847.  
  848.     *usek = k = floor(k) + phase;
  849.     nt1 = 2415020.75933 + synmonth * k
  850.           + 0.0001178 * t2
  851.           - 0.000000155 * t3
  852.           + 0.00033 * dsin(166.56 + 132.87 * t - 0.009173 * t2);
  853.  
  854.     return nt1;
  855.     }
  856.  
  857. /*  TRUEPHASE  --  Given a K value used to determine the
  858.                    mean phase of the new moon, and a phase
  859.                    selector (0.0, 0.25, 0.5, 0.75), obtain
  860.                    the true, corrected phase time.  */
  861.  
  862. double truephase(double k, double phase)
  863.     {
  864.     double t, t2, t3, pt, m, mprime, f;
  865.     int apcor = FALSE;
  866.  
  867.     k += phase;                /* Add phase to new moon time */
  868.     t = k / 1236.85;           /* Time in Julian centuries from
  869.                                   1900 January 0.5 */
  870.     t2 = t * t;                /* Square for frequent use */
  871.     t3 = t2 * t;               /* Cube for frequent use */
  872.     pt = 2415020.75933         /* Mean time of phase */
  873.          + synmonth * k
  874.          + 0.0001178 * t2
  875.          - 0.000000155 * t3
  876.          + 0.00033 * dsin(166.56 + 132.87 * t - 0.009173 * t2);
  877.  
  878.     m = 359.2242               /* Sun's mean anomaly */
  879.         + 29.10535608 * k
  880.         - 0.0000333 * t2
  881.         - 0.00000347 * t3;
  882.     mprime = 306.0253          /* Moon's mean anomaly */
  883.         + 385.81691806 * k
  884.         + 0.0107306 * t2
  885.         + 0.00001236 * t3;
  886.     f = 21.2964                /* Moon's argument of latitude */
  887.         + 390.67050646 * k
  888.         - 0.0016528 * t2
  889.         - 0.00000239 * t3;
  890.     if ((phase < 0.01) || (abs(phase - 0.5) < 0.01))
  891.         {
  892.         /* Corrections for New and Full Moon */
  893.  
  894.         pt +=     (0.1734 - 0.000393 * t) * dsin(m)
  895.                  + 0.0021 * dsin(2 * m)
  896.                  - 0.4068 * dsin(mprime)
  897.                  + 0.0161 * dsin(2 * mprime)
  898.                  - 0.0004 * dsin(3 * mprime)
  899.                  + 0.0104 * dsin(2 * f)
  900.                  - 0.0051 * dsin(m + mprime)
  901.                  - 0.0074 * dsin(m - mprime)
  902.                  + 0.0004 * dsin(2 * f + m)
  903.                  - 0.0004 * dsin(2 * f - m)
  904.                  - 0.0006 * dsin(2 * f + mprime)
  905.                  + 0.0010 * dsin(2 * f - mprime)
  906.                  + 0.0005 * dsin(m + 2 * mprime);
  907.         apcor = TRUE;
  908.         }
  909.     else if ((abs(phase - 0.25) < 0.01 || (abs(phase - 0.75) < 0.01)))
  910.         {
  911.         pt +=     (0.1721 - 0.0004 * t) * dsin(m)
  912.                  + 0.0021 * dsin(2 * m)
  913.                  - 0.6280 * dsin(mprime)
  914.                  + 0.0089 * dsin(2 * mprime)
  915.                  - 0.0004 * dsin(3 * mprime)
  916.                  + 0.0079 * dsin(2 * f)
  917.                  - 0.0119 * dsin(m + mprime)
  918.                  - 0.0047 * dsin(m - mprime)
  919.                  + 0.0003 * dsin(2 * f + m)
  920.                  - 0.0004 * dsin(2 * f - m)
  921.                  - 0.0006 * dsin(2 * f + mprime)
  922.                  + 0.0021 * dsin(2 * f - mprime)
  923.                  + 0.0003 * dsin(m + 2 * mprime)
  924.                  + 0.0004 * dsin(m - 2 * mprime)
  925.                  - 0.0003 * dsin(2 * m + mprime);
  926.         if(phase < 0.5)
  927.             /* First quarter correction */
  928.             pt += 0.0028 - 0.0004 * dcos(m) + 0.0003 * dcos(mprime);
  929.         else
  930.             /* Last quarter correction */
  931.             pt += -0.0028 + 0.0004 * dcos(m) - 0.0003 * dcos(mprime);
  932.         apcor = TRUE;
  933.         }
  934.  
  935.     if(!apcor)
  936.         {
  937.         fprintf(stderr, "TRUEPHASE called with invalid phase selector.\n");
  938.         exit(1);
  939.         }
  940.  
  941.     return pt;
  942.     }
  943.  
  944. /*  PHASEHUNT  --  Find time of phases of the moon which surround
  945.                    the current date.  Five phases are found, starting
  946.                    and ending with the new moons which bound the
  947.                    current lunation.  */
  948.  
  949. void phasehunt(double sdate, double phases[5])
  950.     {
  951.     double adate, k1, k2, nt1, nt2;
  952.  
  953.     adate = sdate - 45;
  954.     nt1 = meanphase(adate, 0.0, &k1);
  955.     while (TRUE)
  956.         {
  957.         adate += synmonth;
  958.         nt2 = meanphase(adate, 0.0, &k2);
  959.         if (nt1 <= sdate && nt2 > sdate)
  960.               break;
  961.         nt1 = nt2;
  962.         k1 = k2;
  963.         }
  964.     phases[0] = truephase(k1, 0.0);
  965.     phases[1] = truephase(k1, 0.25);
  966.     phases[2] = truephase(k1, 0.5);
  967.     phases[3] = truephase(k1, 0.75);
  968.     phases[4] = truephase(k2, 0.0);
  969.     }
  970.  
  971.  
  972. /*  KEPLER  --  Solve the equation of Kepler.  */
  973.  
  974. double kepler(double m, double ecc)
  975.     {
  976.     double e, delta;
  977.  
  978.     e = m = torad(m);
  979.     do 
  980.         {
  981.         delta = e - ecc * sin(e) - m;
  982.         e -= delta / (1 - ecc * cos(e));
  983.         }
  984.     while (abs(delta) > EPSILON);
  985.  
  986.     return e;
  987.     }
  988.  
  989.  
  990. /*  PHASE  --  Calculate phase of moon as a fraction:
  991.  
  992.         The argument is the time for which the phase is requested,
  993.         expressed as a Julian date and fraction.  Returns the terminator
  994.         phase angle as a percentage of a full circle (i.e., 0 to 1),
  995.         and stores into pointer arguments the illuminated fraction of
  996.         the Moon's disc, the Moon's age in days and fraction, the
  997.         distance of the Moon from the centre of the Earth, and the
  998.         angular diameter subtended by the Moon as seen by an observer
  999.         at the centre of the Earth.
  1000.  
  1001.         pphase.............Illuminated fraction 
  1002.         mage...............Age of moon in days 
  1003.         dist...............Distance in kilometres 
  1004.         angdia.............Angular diameter in degrees 
  1005.         sudist.............Distance to Sun 
  1006.         suangdia...........Sun's angular diameter 
  1007. */
  1008.  
  1009. double phase(double pdate, double *pphase, double *mage, double *dist, double *angdia, double *sudist, double *suangdia)
  1010.     {
  1011.     double Day, N, M, Ec, Lambdasun, ml, MM, MN, Ev, Ae, A3, MmP,
  1012.            mEc, A4, lP, V, lPP, NP, y, x, Lambdamoon, BetaM,
  1013.            MoonAge, MoonPhase,
  1014.            MoonDist, MoonDFrac, MoonAng, MoonPar,
  1015.            F, SunDist, SunAng;
  1016.  
  1017.     /* Calculation of the Sun's position */
  1018.  
  1019.     Day = pdate - epoch;        /* Date within epoch */
  1020.     N = fixangle((360 / 365.2422) * Day); /* Mean anomaly of the Sun */
  1021.     M = fixangle(N + elonge - elongp);    /* Convert from perigee co-ordinates to epoch 1980.0 */
  1022.     Ec = kepler(M, eccent);     /* Solve equation of Kepler */
  1023.     Ec = sqrt((1 + eccent) / (1 - eccent)) * tan(Ec / 2);
  1024.     Ec = 2 * todeg(atan(Ec));   /* True anomaly */
  1025.     Lambdasun = fixangle(Ec + elongp);  /* Sun's geocentric ecliptic longitude */
  1026.     F = ((1 + eccent * cos(torad(Ec))) / (1 - eccent * eccent)); /* Orbital distance factor */
  1027.     SunDist = sunsmax / F;      /* Distance to Sun in km */
  1028.     SunAng = F * sunangsiz;     /* Sun's angular size in degrees */
  1029.  
  1030.     /* 
  1031.      *  Calculation of the Moon's position
  1032.      */
  1033.  
  1034.     /* Moon's mean longitude */
  1035.     ml = fixangle(13.1763966 * Day + mmlong);
  1036.  
  1037.     /* Moon's mean anomaly */
  1038.     MM = fixangle(ml - 0.1114041 * Day - mmlongp);
  1039.  
  1040.     /* Moon's ascending node mean longitude */
  1041.     MN = fixangle(mlnode - 0.0529539 * Day);
  1042.  
  1043.     /* Evection */
  1044.     Ev = 1.2739 * sin(torad(2 * (ml - Lambdasun) - MM));
  1045.  
  1046.     /* Annual equation */
  1047.     Ae = 0.1858 * sin(torad(M));
  1048.  
  1049.     /* Correction term */
  1050.     A3 = 0.37 * sin(torad(M));
  1051.  
  1052.     /* Corrected anomaly */
  1053.     MmP = MM + Ev - Ae - A3;
  1054.  
  1055.     /* Correction for the equation of the centre */
  1056.     mEc = 6.2886 * sin(torad(MmP));
  1057.  
  1058.     /* Another correction term */
  1059.     A4 = 0.214 * sin(torad(2 * MmP));
  1060.  
  1061.     /* Corrected longitude */
  1062.     lP = ml + Ev + mEc - Ae + A4;
  1063.  
  1064.     /* Variation */
  1065.     V = 0.6583 * sin(torad(2 * (lP - Lambdasun)));
  1066.  
  1067.     /* True longitude */
  1068.     lPP = lP + V;
  1069.  
  1070.     /* Corrected longitude of the node */
  1071.     NP = MN - 0.16 * sin(torad(M));
  1072.  
  1073.     /* Y inclination coordinate */
  1074.     y = sin(torad(lPP - NP)) * cos(torad(minc));
  1075.  
  1076.     /* X inclination coordinate */
  1077.     x = cos(torad(lPP - NP));
  1078.  
  1079.     /* Ecliptic longitude */
  1080.     Lambdamoon = todeg(atan2(y, x));
  1081.     Lambdamoon += NP;
  1082.  
  1083.     /* Ecliptic latitude */
  1084.     BetaM = todeg(asin(sin(torad(lPP - NP)) * sin(torad(minc))));
  1085.  
  1086.     /*
  1087.      *  Calculation of the phase of the Moon
  1088.      */
  1089.  
  1090.     /* Age of the Moon in degrees */
  1091.     MoonAge = lPP - Lambdasun;
  1092.  
  1093.     /* Phase of the Moon */
  1094.     MoonPhase = (1 - cos(torad(MoonAge))) / 2;
  1095.  
  1096.     /*
  1097.      *  Calculate distance of moon from the centre of the Earth
  1098.      */
  1099.  
  1100.     MoonDist = (msmax * (1 - mecc * mecc)) / (1 + mecc * cos(torad(MmP + mEc)));
  1101.  
  1102.     /*
  1103.      *  Calculate Moon's angular diameter
  1104.      */
  1105.  
  1106.     MoonDFrac = MoonDist / msmax;
  1107.     MoonAng = mangsiz / MoonDFrac;
  1108.  
  1109.     /*
  1110.      *  Calculate Moon's parallax
  1111.      */
  1112.  
  1113.     MoonPar = mparallax / MoonDFrac;
  1114.  
  1115.     *pphase = MoonPhase;
  1116.     *mage = synmonth * (fixangle(MoonAge) / 360.0);    /* ???? This can't be right ???? */
  1117.     *dist = MoonDist;
  1118.     *angdia = MoonAng;
  1119.     *sudist = SunDist;
  1120.     *suangdia = SunAng;
  1121.     return fixangle(MoonAge) / 360.0;
  1122.     }
  1123.